package net.zoneland.knowledge.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

import com.google.common.collect.Sets;

import net.zoneland.knowledge.constant.BizConstant;
import net.zoneland.knowledge.constant.FieldConstant;
import net.zoneland.knowledge.enums.LevelEnum;
import net.zoneland.knowledge.enums.QueryTypeEnum;
import net.zoneland.knowledge.enums.TypeEnum;
import net.zoneland.knowledge.enums.VisitTypeEnum;
import net.zoneland.knowledge.model.EsQuestion;
import net.zoneland.knowledge.model.QaQueryDto;
import net.zoneland.knowledge.model.QaResponse;

/**
 * .
 *
 * @author: bcc
 * 2021/5/26
 */
public final class ResponseUtils {
    /**
     * 私有构造.
     */
    private ResponseUtils() {

    }

    public static QaResponse assembleResponse(final EsQuestion esQuestion, final QaQueryDto qaQueryDto) {
        QaResponse qaResponse = new QaResponse();
        Map<String, Object> map = transferEsQuestion(esQuestion, qaQueryDto);
        qaResponse.setType(TypeEnum.OBJECT.getValue());
        qaResponse.setData(map);
        qaResponse.setWordTokens(qaQueryDto.getWordTokens());
        return qaResponse;
    }



    public static Map<String, Object> transferEsQuestion(final EsQuestion esQuestion, final QaQueryDto qaQueryDto) {
        Map<String, Object> map = new HashMap<>(12);
        map.put(FieldConstant.FIELD_ID, esQuestion.getId());
        map.put(FieldConstant.FIELD_CATEGORY, esQuestion.getCategory());
        map.put(FieldConstant.FIELD_LEVEL1TITLE, esQuestion.getLevel1Title());
        map.put(FieldConstant.FIELD_LEVEL2TITLE, esQuestion.getLevel2Title());
        map.put(FieldConstant.FIELD_LEVEL3TITLE, esQuestion.getLevel3Title());
        map.put(FieldConstant.FIELD_FAVORITE, esQuestion.isFavorite());
        map.put(FieldConstant.FIELD_QUESTION, esQuestion.getQuestion());
        if (StringUtils.isNotBlank(esQuestion.getOrgDeptDn())) {
            map.put(FieldConstant.FIELD_CURRENCY, Boolean.FALSE);
        } else {
            map.put(FieldConstant.FIELD_CURRENCY, Boolean.TRUE);
        }
        map.put(FieldConstant.FIELD_ROBOT_NAME, esQuestion.getRobotName());
        //没有用到先注释了
        //        if (StringUtils.isNotBlank(esQuestion.getExtendsInfo())) {
        //            map.put(FieldConstant.FIELD_EXTEND_INFO, GsonUtils.GSON.fromJson(esQuestion.getExtendsInfo(), Map.class));
        //        }
        if (StringUtils.isNotBlank(esQuestion.getCustomizedInfo())) {
            map.put(FieldConstant.FIELD_CUSTOMIZED_INFO, GsonUtils.GSON.fromJson(esQuestion.getCustomizedInfo(), Map.class));
        }
        Map<String, Object> dataFormDb = esQuestion.getDataFormDb();
        if (null != dataFormDb) {
            if (null != dataFormDb.get(FieldConstant.FIELD_ANS_CONTENT_FILE_LIST)) {
                map.put(FieldConstant.FIELD_ANS_CONTENT_FILE_LIST, dataFormDb.get(FieldConstant.FIELD_ANS_CONTENT_FILE_LIST));
            }
            if (null != dataFormDb.get(FieldConstant.FIELD_ANS_CONTENT_IMAGE_LIST)) {
                map.put(FieldConstant.FIELD_ANS_CONTENT_IMAGE_LIST, dataFormDb.get(FieldConstant.FIELD_ANS_CONTENT_IMAGE_LIST));
            }
        }

        map.put(FieldConstant.FIELD_SHOW_RICH_TEXT, esQuestion.getShowRichText());
        map.put(FieldConstant.FIELD_CONTENT, esQuestion.getAnswer());
        map.put(FieldConstant.FIELD_SUBJECT, esQuestion.isSubject());
        return map;
    }

    /**
     * 返回类似如下结构的数据.
     *  [
     *         {
     *             "category": "RHB",
     *             "title": "入职离职管理",
     *             "subList": [
     *                 {
     *                     "id":" RHB-RHB-1-12",
     *                     "level1Title": "入职离职管理",
     *                     "level2Title": "我要入职",
     *                     "extendInfo": {
     *                         "timeLimit":"工作时间内即到即盖",
     *                         "workCommitment":"针对符合公司规定的人事主管部门用章内容，做好用印管理工作。",
     *                         "leader":"黄慧",
     *                         "targetUser":"李强",
     *                         "remark":"盖章内容符合公司规定。"
     *                     },
     * "customizedInfo":[
     *        {
     *      "title":"title",
     *      "info":"info"
     *    }
     *  ]
     *
     * @param esQuestions 查询结果,已经是同一数据分类了
     * @param qaQueryDto 查询参数对象
     * @param level 层级
     * @return 处理后的数据
     */
    public static List<Map<String, Object>> generateResponse(final List<EsQuestion> esQuestions,
                                                             final QaQueryDto qaQueryDto, final LevelEnum level) {
        if (QueryTypeEnum.QUERY_BY_PATH == qaQueryDto.getQaType()) {
            return generateResponseForQueryByPath(esQuestions, level, qaQueryDto);
        } else {
            return generateResponseForQuerySearch(esQuestions, qaQueryDto);
        }
    }

    /**
     * 普通查询的返回结果就两种情况：
     * 一级科目：
     *    二级科目：二级科目可能是二级科目，也可能是问题
     *  对应的返回给前台时要间接的反映出是哪一种：(根据是否有ID返回来判断)
     *      如果是科目，下一级查询则是queryByPath
     *      如果是题干，点击栏目查询是queryById
     * @param esQuestions
     * @param qaQueryDto
     * @return
     */
    private static List<Map<String, Object>> generateResponseForQuerySearch(final List<EsQuestion> esQuestions,
                                                                            final QaQueryDto qaQueryDto) {
        List<Map<String, Object>> list = new ArrayList<>();

        // 这里的category都一样
        String category = esQuestions.get(0).getCategory();
        //获取一级科目顺序
        List<String> level1Titles = new ArrayList<>();
        for (EsQuestion esQuestion : esQuestions) {
            if (esQuestion.getLevel1Title().contains(qaQueryDto.getQueryText())) {
                if (!level1Titles.contains(esQuestion.getLevel1Title())) {
                    level1Titles.add(esQuestion.getLevel1Title());
                }
            }
        }

        for (EsQuestion esQuestion : esQuestions) {
            if (!level1Titles.contains(esQuestion.getLevel1Title())) {
                level1Titles.add(esQuestion.getLevel1Title());
            }
        }
        for (String level1Title : level1Titles) {
            Map<String, Object>  result = new LinkedHashMap<>();
            Set<String> addedEsIds = Sets.newHashSet();
            result.put(FieldConstant.FIELD_CATEGORY, category);
            result.put(FieldConstant.FIELD_LEVEL1TITLE, level1Title);
            List<Map<String, Object>> subList = new ArrayList<>();
            for (EsQuestion esQuestion : esQuestions) {
                if (level1Title.equals(esQuestion.getLevel1Title())) {
                    if (StringUtils.isNotBlank(esQuestion.getId())
                        && addedEsIds.contains(esQuestion.getId())) {
                        // 防止重复添加
                        continue;
                    }
                    Map<String, Object> map = ResponseUtils.transferEsQuestion(esQuestion, qaQueryDto);
                    //有二级科目时不要返回ID
                    if (StringUtils.isNotBlank(esQuestion.getLevel2Title())) {
                        map.remove(FieldConstant.FIELD_ID);
                    }
                    map.remove(FieldConstant.FIELD_CATEGORY);
                    map.remove(FieldConstant.FIELD_LEVEL3TITLE);
                    subList.add(map);
                    if (StringUtils.isNotBlank(esQuestion.getId())) {
                        addedEsIds.add(esQuestion.getId());
                    }
                }
            }
            result.put(FieldConstant.FIELD_SUB_LIST, subList);
            list.add(result);
        }

        return list;
    }

    /**
     * 根据路径返回查询结果时.
     * 返回的是root的下一级
     * @param esQuestions
     * @param level
     *
     * @return
     */
    private static List<Map<String, Object>> generateResponseForQueryByPath(final List<EsQuestion> esQuestions,
                                                                            final LevelEnum level,
                                                                            final QaQueryDto qaQueryDto) {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object>  result = new LinkedHashMap<>();
        // 这里的category都一样
        final EsQuestion question = esQuestions.get(0);
        String category = question.getCategory();
        result.put(FieldConstant.FIELD_CATEGORY, category);
        level.setLevelTitle(result, question);
        List<Map<String, Object>> subList = new ArrayList<>();
        for (EsQuestion esQuestion : esQuestions) {
            Map<String, Object> map = ResponseUtils.transferEsQuestion(esQuestion, qaQueryDto);
            if (level.removeId(esQuestion)) {
                map.remove(FieldConstant.FIELD_ID);
            }
            level.generateSubLevelTitle(map, esQuestion);
            subList.add(map);
        }
        result.put(FieldConstant.FIELD_SUB_LIST, subList);
        list.add(result);
        return list;
    }

    public static QaResponse generateNoAnswer(final String robotname, final String noAnswer) {
        String tmpRobotName = robotname;
        if (StringUtils.isEmpty(tmpRobotName)) {
            tmpRobotName = "小R";
        }
        QaResponse qaResponse = new QaResponse();
        qaResponse.setType(TypeEnum.TEXT.getValue());
        if (StringUtils.isNotBlank(noAnswer)) {
            qaResponse.setData(noAnswer.replaceAll(BizConstant.REPLACE_ROBOT_NAME, tmpRobotName));
        }else {
            qaResponse.setData("十分抱歉，robotName暂时未匹配到您的问题，我们会扩充知识库，期待再次为您服务！".
                replaceAll(BizConstant.REPLACE_ROBOT_NAME, tmpRobotName));
        }
        return qaResponse;
    }

    public static QaResponse generateNoAnswerForFavorite(final String noAnswer) {
        QaResponse qaResponse = new QaResponse();
        qaResponse.setType(TypeEnum.TEXT.getValue());
        if(StringUtils.isNotBlank(noAnswer)) {
            qaResponse.setData(noAnswer);
        } else {
            qaResponse.setData("对不起，您还没有收藏任何信息。请点亮信息右侧的五角星图标，将您需要的信息收藏到“我的收藏”中吧！");
        }
        return qaResponse;
    }



    public static List<EsQuestion> esResultToList(final SearchHits hits1) {
        List<EsQuestion> result = new ArrayList<>();
        SearchHit[] hits2 = hits1.getHits();
        if (hits2.length > 0) {
            for (SearchHit hit : hits2) {
                String qaString = hit.getSourceAsString();
                EsQuestion esQuestion = GsonUtils.GSON.fromJson(qaString, EsQuestion.class);
                result.add(esQuestion);
            }
        }
        return result;
    }
}
